
#include "connection.h"
#include "server.h"
#include <cstdint>
#include <functional>
#include <memory>
#include <sys/socket.h>
#include <unistd.h>


Connection::Connection(Loop * loop, Server * server, std::shared_ptr<TcpSocket> socket)
{
    m_socket = socket;
    m_loop   = loop;
    m_server = server;
    m_channel= std::make_shared<Channel>(loop, socket);
    m_socket_buffer = std::make_shared<SocketBuffer>(socket);
    m_channel->ReadFuncCallback(std::bind(&Connection::ReadAble, this, std::placeholders::_1, std::placeholders::_2));
    m_channel->WriteFuncCallback(std::bind(&Connection::WriteAble, this, std::placeholders::_1, std::placeholders::_2));
    m_channel->ErrFuncCallback(std::bind(&Connection::ErrorAble,   this, std::placeholders::_1, std::placeholders::_2));
    m_channel->AddEvent(EmIoIn | EmIoErr | EmIoRdHup | EmIoOneShot);
}

Connection::~Connection()
{
    TRACE("free connection");
}

int64_t Connection::Index()
{
    return m_channel ? m_channel->Index() : 0;
}

void Connection::ReadAble(std::shared_ptr<Channel> channel, std::shared_ptr<TcpSocket> socket)
{
    int size = m_socket_buffer->ReadData();
    TRACE("index {} and result {}", channel->Index(), size);
    if (size < 0 && m_socket_buffer->GetBufferLength() <= 0)
    {
        m_server->DisConnFromConn(shared_from_this());
        m_channel->DelEvent();    
    }
    else if (size < 0 && m_socket_buffer->GetBufferLength() > 0)
    {
        m_server->MessageFromConn(shared_from_this(), m_socket_buffer);
        m_server->DisConnFromConn(shared_from_this());
        m_channel->DelEvent();
        // and call disconnection;
    }
    else
    {
        m_server->MessageFromConn(shared_from_this(), m_socket_buffer);
        m_channel->ModEvent(EmIoIn | EmIoErr | EmIoRdHup | EmIoOneShot);
    }
}

void Connection::WriteAble(std::shared_ptr<Channel> channel,std::shared_ptr<TcpSocket> socket)
{
}

void Connection::ErrorAble(std::shared_ptr<Channel> channel,std::shared_ptr<TcpSocket> socket)
{
    m_server->DisConnFromConn(shared_from_this());
    m_channel->DelEvent();
}

void Connection::Close()
{
    m_channel->DelEvent();
    m_socket->Close();
    auto self = shared_from_this();
    m_loop->AddPendingTask([self](){
            
        self->m_server->DisConnFromConn(self);
    });
}

int Connection::SendData(const uint8_t * data, int length)
{
    return write(m_socket->GetSocket(), data, length);
}

